/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.biz.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import me.zhengjie.modules.biz.domain.Lab;
import me.zhengjie.modules.biz.domain.LabTime;
import me.zhengjie.modules.biz.repository.LabBusyTimeRepository;
import me.zhengjie.modules.biz.repository.LabRepository;
import me.zhengjie.modules.biz.service.dto.CabinetDto;
import me.zhengjie.modules.biz.service.dto.LabBusyTimeDto;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.biz.repository.LabTimeRepository;
import me.zhengjie.modules.biz.service.LabTimeService;
import me.zhengjie.modules.biz.service.dto.LabTimeDto;
import me.zhengjie.modules.biz.service.dto.LabTimeQueryCriteria;
import me.zhengjie.modules.biz.service.mapstruct.LabTimeMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://eladmin.vip
* @description 服务实现
* @author Admin
* @date 2023-02-17
**/
@Service
@RequiredArgsConstructor
public class LabTimeServiceImpl implements LabTimeService {

    private final LabTimeRepository labTimeRepository;
    private final LabTimeMapper labTimeMapper;
    private final LabRepository labRepository;

    private final LabBusyTimeRepository labBusyTimeRepository;

    @Override
    public Map<String,Object> queryAll(LabTimeQueryCriteria criteria, Pageable pageable){
        Page<LabTime> page = labTimeRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        Page<LabTimeDto> dto = page.map(labTimeMapper::toDto);
        List<LabTimeDto> resultDto = dto.getContent();
        for (LabTimeDto labTimeDto:resultDto) {
            Lab lab = labRepository.findById(labTimeDto.getLabId()).orElseGet(Lab::new);
            labTimeDto.setLabName(lab.getName());
        }
        return PageUtil.toPage(dto);
    }

    @Override
    public List<LabTimeDto> queryAll(LabTimeQueryCriteria criteria){
        List<LabTime> labTimeList = labTimeRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
        List<LabTimeDto> labTimeDtoList = labTimeMapper.toDto(labTimeList);
        String tempMonth = "";
        String tempWeek = "";
        for (LabTimeDto labTimeDto : labTimeDtoList) {
            String month = "";
            String monthsList = labTimeDto.getMonths();
            JSONArray array = JSONUtil.parseArray(monthsList);
            Integer[] monthsArray = array.toArray(new Integer[0]);

            for (int i : monthsArray) {
                switch (i) {
                    case 1:
                        tempMonth = "一月";
                        break;
                    case 2:
                        tempMonth = "二月";
                        break;
                    case 3:
                        tempMonth = "三月";
                        break;
                    case 4:
                        tempMonth = "四月";
                        break;
                    case 5:
                        tempMonth = "五月";
                        break;
                    case 6:
                        tempMonth = "六月";
                        break;
                    case 7:
                        tempMonth = "七月";
                        break;
                    case 8:
                        tempMonth = "八月";
                        break;
                    case 9:
                        tempMonth = "九月";
                        break;
                    case 10:
                        tempMonth = "十月";
                        break;
                    case 11:
                        tempMonth = "十一月";
                        break;
                    case 12:
                        tempMonth = "十二月";
                        break;
                }

                month = (new StringBuilder()).append(month).append(tempMonth).append(",").toString();
            }
            month = month.substring(0, month.length() - 1);
            labTimeDto.setMonthStr(month);

            String weekList = labTimeDto.getWeeks();
            array = JSONUtil.parseArray(weekList);
            Integer[] weeksArray = array.toArray(new Integer[0]);
            String week = "";

            for (int i : weeksArray) {
                switch (i) {
                    case 1:
                        tempWeek = "周一";
                        break;
                    case 2:
                        tempWeek = "周二";
                        break;
                    case 3:
                        tempWeek = "周三";
                        break;
                    case 4:
                        tempWeek = "周四";
                        break;
                    case 5:
                        tempWeek = "周五";
                        break;
                    case 6:
                        tempWeek = "周六";
                        break;
                    case 7:
                        tempWeek = "周日";
                        break;
                }

                week = (new StringBuilder()).append(week).append(tempWeek).append(",").toString();
            }

            week = week.substring(0, week.length() - 1);
            labTimeDto.setWeekStr(week);

            String bookTime = labTimeDto.getBookTime();
            array = JSONUtil.parseArray(bookTime);
            String timeStr = "";
            String startTime = "";
            String endTime = "";
            for (int i = 0; i < array.size(); i++) {
                startTime = array.getJSONObject(i).getStr("start");
                endTime = array.getJSONObject(i).getStr("end");
                timeStr = (new StringBuilder()).append(timeStr).append(startTime).append("-").append(endTime).append(" ").toString();
            }

            labTimeDto.setTimeStr(timeStr);

            Lab lab = labRepository.findById(labTimeDto.getLabId()).orElseGet(Lab::new);
            labTimeDto.setLabName(lab.getName());
        }
        return labTimeDtoList;
    }

    @Override
    @Transactional
    public LabTimeDto findById(Integer id) {
        LabTime labTime = labTimeRepository.findById(id).orElseGet(LabTime::new);
        ValidationUtil.isNull(labTime.getId(),"LabTime","id",id);
        return labTimeMapper.toDto(labTime);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LabTimeDto create(LabTime resources) {
        resources.setCreatorId(Convert.toInt(SecurityUtils.getCurrentUserId()));
        return labTimeMapper.toDto(labTimeRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(LabTime resources) {
        LabTime labTime = labTimeRepository.findById(resources.getId()).orElseGet(LabTime::new);
        ValidationUtil.isNull( labTime.getId(),"LabTime","id",resources.getId());
        labTime.copy(resources);
        labTimeRepository.save(labTime);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            labTimeRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<LabTimeDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (LabTimeDto labTime : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("实验室", labTime.getLabName());
            map.put("月份", labTime.getMonthStr());
            map.put("周", labTime.getWeekStr());
            map.put("通用时间段", labTime.getTimeStr());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Map<String, Object> queryLabTimeById(Integer labId) {
        Map<String, Object> labTimeMap = new HashMap<>();
        LabTime labTime = labTimeRepository.findByLabId(labId);
//        String bookTime = labTime.getBookTime();
//        JSONArray array = JSONUtil.parseArray(bookTime);
        //String[] bookTimeArray = array.toArray(new String[0]);
        String months = labTime.getMonths();
        JSONArray array = JSONUtil.parseArray(months);
        Integer[] monthsArray = array.toArray(new Integer[0]);
        //List<String> monthsList = Arrays.asList(months.split(","));
        //int[] monthsArray = monthsList.stream().mapToInt(Integer::parseInt).toArray();
        String weeks = labTime.getWeeks();
        array = JSONUtil.parseArray(weeks);
        Integer[] weeksArray = array.toArray(new Integer[0]);
        //List<String> weeksList = Arrays.asList(weeks.split(","));
        //int[] weeksArray = weeksList.stream().mapToInt(Integer::parseInt).toArray();
        int year = Convert.toInt(Convert.toStr(labTime.getUpdatedAt()).substring(0,4));
        List<String> datesDetails = new LinkedList<>();
        try {
            for (int i : monthsArray) {
                for (int j : weeksArray) {
//                    switch (j) {
//                        case 1:
//                            datesDetails.addAll(DateUtil.getWeekS(year, i, "星期一"));
//                            break;
//                        case 2:
//                            datesDetails.addAll(DateUtil.getWeekS(year, i, "星期二"));
//                            break;
//                        case 3:
//                            datesDetails.addAll(DateUtil.getWeekS(year, i, "星期三"));
//                            break;
//                        case 4:
//                            datesDetails.addAll(DateUtil.getWeekS(year, i, "星期四"));
//                            break;
//                        case 5:
//                            datesDetails.addAll(DateUtil.getWeekS(year, i, "星期五"));
//                            break;
//                        case 6:
//                            datesDetails.addAll(DateUtil.getWeekS(year, i, "星期六"));
//                            break;
//                        case 7:
//                            datesDetails.addAll(DateUtil.getWeekS(year, i, "星期日"));
//                            break;
//                    }
                    switch (j) {
                        case 1:
                            datesDetails.addAll(DateUtil.getWeekS(year, i, "周一"));
                            break;
                        case 2:
                            datesDetails.addAll(DateUtil.getWeekS(year, i, "周二"));
                            break;
                        case 3:
                            datesDetails.addAll(DateUtil.getWeekS(year, i, "周三"));
                            break;
                        case 4:
                            datesDetails.addAll(DateUtil.getWeekS(year, i, "周四"));
                            break;
                        case 5:
                            datesDetails.addAll(DateUtil.getWeekS(year, i, "周五"));
                            break;
                        case 6:
                            datesDetails.addAll(DateUtil.getWeekS(year, i, "周六"));
                            break;
                        case 7:
                            datesDetails.addAll(DateUtil.getWeekS(year, i, "周日"));
                            break;
                    }
                }
            }
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        labTimeMap.put("bookTime", labTime);
        labTimeMap.put("bookedTime", labBusyTimeRepository.findByLabIdAndStatus(labId, 2));
        labTimeMap.put("datesDetail", datesDetails);
//        labTimeMap.put("monthsArray", monthsArray);
//        labTimeMap.put("weeksArray", weeksArray);
//        labTimeMap.put("bookTimeArray", bookTimeArray);
        return labTimeMap;
    }

    @Override
    public List<LabTimeDto> queryLab() {
        List<LabTimeDto> labTimeDtos = labTimeMapper.toDto(labTimeRepository.findAll());
        for (LabTimeDto labTimeDto:labTimeDtos) {
            Lab lab = labRepository.findById(labTimeDto.getLabId()).orElseGet(Lab::new);
            labTimeDto.setLabName(lab.getName());
        }
        return labTimeDtos;
    }

}
